﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using ServiceBus.Contract;
using System.Resources;

namespace ServiceBus.EndPoint
{
    
    public class MessageDistributor : ServiceBus.Contract.IMessageSenderCallBack
    {
        #region Server Event
        public event EventHandler<Message> MessageDelivered;
        public event EventHandler ServerConnectedEvent;
        public event EventHandler ServerDisconnectedEvent;
        public event EventHandler HeartBeatFromServer;
        #endregion

        #region Properties
        private int _ServerConnected = 0;
        public bool ServerConnected
        {
            get
            {
                if (_ServerConnected < 0) return false;
                else return true;
            }
        }

        private System.Windows.Forms.Timer ServerConnectionChecker = null;

        private MessageSenderProxy MessageSender = null;

        private static Dictionary<string ,MessageDistributor> _MessageServiceList = new Dictionary<string,MessageDistributor>();
        public static MessageDistributor[] MessageServiceList
        {
            get
            {
                return _MessageServiceList.Values.ToArray();
            }
        }
        public static MessageDistributor CreateMessageService(string servicename, string address)
        {
            MessageDistributor dis = null;
            if (_MessageServiceList.Keys.Contains(servicename.ToUpper().Trim()))
            {
                dis = _MessageServiceList[servicename.ToUpper().Trim()];
            }
            else
            {
                dis = new MessageDistributor(servicename,address);
                _MessageServiceList.Add(servicename.ToUpper(), dis);
            }
            return dis;
        }
        public static MessageDistributor GetMessageService(string servicename)
        {
            if (_MessageServiceList.Keys.Contains(servicename.ToUpper().Trim()))
            {
                return _MessageServiceList[servicename.ToUpper().Trim()];
            }
            else return null;
        }
        public static void CloseMessageService(string servicename)
        {
            MessageDistributor message = GetMessageService(servicename);
            if (message != null)
            {
                message.Close();
                _MessageServiceList.Remove(servicename.ToUpper().Trim());
            }
        }
        #endregion

        #region Constructor
        /// <summary>
        /// constructor. set time to detect if server is connected
        /// </summary>
        private MessageDistributor(string endpointpath,string address)
        {
            this.ServerConnectionChecker = new System.Windows.Forms.Timer();
            this.ServerConnectionChecker.Interval = 1000 * 10;
            this.ServerConnectionChecker.Tick += new EventHandler(ServerConnectionChecker_Elapsed);
            this.ServerConnectionChecker.Start();
            this.ServiceName = endpointpath;
            this.Address = address+"Message";
            this.Refresh();
        }
        private MessageDistributor(string endpointpath):this(endpointpath,string.Empty)
        {
            
        }

        void ServerConnectionChecker_Elapsed(object sender, EventArgs e)
        {
            switch (this._ServerConnected)
            {
                case 1:
                    this._ServerConnected = 0;
                    break;
                case 0:
                    this._ServerConnected = -1;
                    break;
                case -1:
                    this.Refresh();
                    break;
                default:
                    break;
            }
        }
        #endregion

        #region Methods
        public void SendMessage(Message message)
        {
            try
            {
                if (MessageDelivered != null) MessageDelivered(null, message);
            }
            catch (Exception ex) { Console.WriteLine(ex.Message); }
        }
        public void SendHeartBeat(string address)
        {
            if (this._ServerConnected == -1)
            {
                if (ServerConnectedEvent != null)
                {
                    try
                    {
                        ServerConnectedEvent(address, null);
                    }
                    catch { }
                }
            }
            this._ServerConnected = 1;
            if (HeartBeatFromServer != null) HeartBeatFromServer(address, null);
        }
        public string ServiceName { get; private  set; }
        public string Address { get; private set; }
        public void Refresh()
        {
            try
            {
                try
                {
                    if (this.MessageSender != null)
                    {
                        this.MessageSender.Abort();
                    }
                }
                catch { }
                InstanceContext instanceContext = new InstanceContext(this);
                if (this.Address == string.Empty)
                {
                    this.MessageSender = new MessageSenderProxy(instanceContext, "MessageSender");
                }
                else
                {
                    System.ServiceModel.Channels.Binding bind = new NetTcpBinding();
                    EndpointAddress add = new EndpointAddress(this.Address);
                    this.MessageSender = new MessageSenderProxy(instanceContext,bind,add);
                }
                this.MessageSender.Init(ServiceName);
            }
            catch (Exception ex)
            {
                if (ServerDisconnectedEvent != null)
                {
                    try
                    {
                        ServerDisconnectedEvent(Address, null);
                    }
                    catch { }
                }
                this._ServerConnected = -1;
            }
        }
        private void Close()
        {
            try
            {
                this.MessageSender.Abort();


            }
            catch { }
            finally
            {
                this.ServerConnectionChecker.Stop();
                this.ServerConnectionChecker.Dispose();
            }
        }

        #endregion

    }
}
